/*****************************************************************************
 * menus.cc : Gtkmmm interface
 ****************************************************************************
 * Copyright © 2006-2008 the VideoLAN team
 *
 * Authors: David Guglielmi <raxxx.fr@gmail.com>
 *          David LARROQUE <snio.fr@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include <gtkmm/main.h>
#include <gtkmm/menu.h>
#include <gtkmm/image.h>
#include <gtkmm/imagemenuitem.h>
#include <gtkmm/radiomenuitem.h>
#include <gtkmm/separatormenuitem.h>

#include "menus.hh"
#include "gtkmm.hh"
#include "util/string.hh"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <vlc/vlc.h>
#include <vlc_intf_strings.h>
#include <vlc_services_discovery.h>

#include <iomanip>
#include <sstream>

enum
{
  ITEM_NORMAL,
  ITEM_CHECK,
  ITEM_RADIO
};

static Gtk::RadioMenuItem::Group current_group;

/* Macros ********************************************************************/
// FIXME add action param with "_item->signal_activate ().connect (param);"
#define ADD_SEPARATOR {menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));}

#define ADD_IMG_ITEM(imagename, text, accel, modifiertype) { \
    image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_file (Glib::ustring (config_GetDataDir ()) + "/gvlc/"+imagename))), q2gm (_(text)), true); \
    image_item->add_accelerator ("activate", toplevel->get_accel_group (), accel, modifiertype, Gtk::ACCEL_VISIBLE); \
    menu->append (*Gtk::manage (image_item));}

#define ADD_TXT_ITEM(text, accel, modifiertype) { \
    sub_item = new Gtk::MenuItem (_(text)); \
    sub_item->add_accelerator ("activate", toplevel->get_accel_group (), accel, modifiertype, Gtk::ACCEL_VISIBLE); \
    menu->append (*Gtk::manage (sub_item));}

#define ADD_CHK_ITEM(text, accel, modifiertype) { \
    check_item = new Gtk::CheckMenuItem (_(text), false); \
    if (accel) check_item->add_accelerator ("activate", toplevel->get_accel_group (), accel, modifiertype, Gtk::ACCEL_VISIBLE); \
    menu->append (*Gtk::manage (check_item));}

#define PUSH_VAR(var) varnames.push_back(var); \
    objects.push_back(p_object ? p_object->i_object_id 0);

#define PUSH_INPUTVAR(var) varnames.push_back(var); \
    objects.push_back(p_input ? p_input->i_object_id : 0);

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuBar*
GVLCMenu::create_menu_bar (Gtk::Window *window, intf_thread_t *p_intf)
{

  Gtk::MenuBar *menu_bar = new Gtk::MenuBar ();
  
  menu_bar->append (*file_menu (window));
  menu_bar->append (*playlist_menu (window, p_intf));
  menu_bar->append (*tools_menu (window));
  menu_bar->append (*audio_menu (p_intf));
  menu_bar->append (*video_menu (p_intf));
  menu_bar->append (*playback_menu (window, p_intf));
  menu_bar->append (*help_menu (window));

  (void) p_intf;

  return menu_bar;

}

// File Menu  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::file_menu (Gtk::Window *toplevel)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Media")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item;

  ADD_IMG_ITEM ("vlc_open_file.png", "&Open File...", GDK_O, Gdk::CONTROL_MASK);
  // FIXME: Open D&irectory is i18n with the accelerator :s
  ADD_IMG_ITEM ("vlc_open_dir.png", "Open D&irectory...", GDK_F, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_open_disc.png", "Open &Disc...", GDK_D, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_open_network.png", "Open &Network...", GDK_N, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_capture_device.png", "Open &Capture Device...", GDK_C, Gdk::CONTROL_MASK);
  ADD_SEPARATOR;
  ADD_IMG_ITEM ("vlc_stream.png", "&Streaming...", GDK_S, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_convert.png", "Conve&rt / Save...", GDK_R, Gdk::CONTROL_MASK);
  ADD_SEPARATOR;
  ADD_IMG_ITEM ("vlc_quit.png", "&Quit", GDK_Q, Gdk::CONTROL_MASK);
  image_item->signal_activate ().connect (sigc::ptr_fun (&Gtk::Main::quit)); //FIXME

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Playlist Menu  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::playlist_menu (Gtk::Window *toplevel, intf_thread_t *p_intf)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Playlist")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item;
  Gtk::MenuItem *sub_item;

  menu->append (*Gtk::manage (playlist_sd_submenu (p_intf)));
  ADD_IMG_ITEM ("vlc_playlist.png", "Show Playlist", GDK_L, Gdk::CONTROL_MASK);
  ADD_SEPARATOR;
  ADD_IMG_ITEM ("vlc_playlist_open.png", I_PL_LOAD, GDK_X, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_save.png", I_PL_SAVE, GDK_Y, Gdk::CONTROL_MASK);
  ADD_SEPARATOR;
  ADD_TXT_ITEM ("Undock from interface", GDK_U, Gdk::CONTROL_MASK);

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Tools Menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::tools_menu (Gtk::Window *toplevel)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Tools")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item;
  Gtk::CheckMenuItem *check_item;
  Gtk::MenuItem *sub_item;

  ADD_IMG_ITEM ("vlc_ext_settings.png", I_MENU_EXT, GDK_E, Gdk::CONTROL_MASK);
  ADD_SEPARATOR;

  // Interface Sub-menu
/* if (with_intf) // FIXME
 {
   menu->append (*Gtk::manage (create_interfaces_menu ()));
   menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));
 }
*/

  ADD_CHK_ITEM ("Minimal View...", GDK_H, Gdk::CONTROL_MASK);
  ADD_CHK_ITEM ("Toggle Fullscreen Interface", GDK_F11, Gdk::LOCK_MASK);
  check_item = new Gtk::CheckMenuItem (_("Advanced controls"), false);
  menu->append (*Gtk::manage (check_item));
  ADD_SEPARATOR;
  ADD_IMG_ITEM ("vlc_messages.png", I_MENU_MSG, GDK_M, Gdk::CONTROL_MASK);
  //image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::messages));
  ADD_IMG_ITEM ("vlc_media_info.png", I_MENU_INFO, GDK_I, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_media_info.png", I_MENU_CODECINFO, GDK_J, Gdk::CONTROL_MASK);
  ADD_IMG_ITEM ("vlc_bookmark.png", I_MENU_BOOKMARK, GDK_B, Gdk::CONTROL_MASK);
#ifdef ENABLE_VLM
  ADD_TXT_ITEM (I_MENU_VLM, GDK_V, Gdk::CONTROL_MASK);
#endif
  ADD_SEPARATOR;
  ADD_IMG_ITEM ("vlc_pref.png", "Preferences...", GDK_P, Gdk::CONTROL_MASK);

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Audio Menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::audio_menu (intf_thread_t *p_intf)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Audio")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  vlc_object_t *p_aout;
  input_thread_t *p_input;
  std::vector<int> objects;
  std::vector<const char *> varnames;

//  p_input = THEMIM->getInput();
  if (p_input)
    vlc_object_yield (p_input);
  p_aout = (vlc_object_t *) vlc_object_find (p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE);

  PUSH_INPUTVAR ("audio-es");
  PUSH_VAR ("audio-device");
  PUSH_VAR ("audio-channels");
  PUSH_VAR ("visual");
  PUSH_VAR ("equalizer");

  if (p_aout)
    vlc_object_release (p_aout);
  if (p_input)
    vlc_object_release (p_input);

  Populate (menu, varnames, objects);

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Video Menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::video_menu (intf_thread_t *p_intf)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Video")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  vlc_object_t *p_vout;
  input_thread_t *p_input;
  std::vector<int> objects;
  std::vector<const char *> varnames;

  Gtk::MenuItem *sub_item;

  sub_item = new Gtk::MenuItem (q2gm(_("Video &Track")), true);
  menu->append (*Gtk::manage (sub_item));

  sub_item = new Gtk::MenuItem (q2gm (_("&Subtitles Track")), true);
  Gtk::Menu *sub_menu = new Gtk::Menu ();
  Gtk::MenuItem *sub_sub_item = new Gtk::MenuItem (_("Load File..."));
  sub_menu->append (*Gtk::manage (sub_sub_item));
  sub_item->set_submenu (*Gtk::manage (menu));
  menu->append (*Gtk::manage (sub_item));
  ADD_SEPARATOR;

  p_input = THEMIM->getInput();
  if (p_input)
    vlc_object_yield (p_input);

  p_vout = (vlc_object_t *)vlc_object_find(p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE);

  if (p_object != NULL)
  {
    PUSH_INPUTVAR ("video-es");
    PUSH_INPUTVAR ("spu-es");
    PUSH_VAR ("fullscreen");
    PUSH_VAR ("zoom");
    PUSH_VAR ("deinterlace");
    PUSH_VAR ("aspect-ratio");
    PUSH_VAR ("crop");
    PUSH_VAR ("video-on-top");
    PUSH_VAR ("directx-wallpaper");
    PUSH_VAR ("video-snapshot");

    if (p_object)
    {
        vlc_object_t *p_dec_obj = (vlc_object_t *)vlc_object_find(p_object, VLC_OBJECT_DECODER, FIND_PARENT);
        if (p_dec_obj)
        {
          vlc_object_t *p_object = p_dec_obj;
          PUSH_VAR ("ffmpeg-pp-q");
          vlc_object_release (p_dec_obj);
        }
    }
  }

  if (p_vout)
    vlc_object_release (p_vout);
  if (p_input)
    vlc_object_release (p_input);

  Populate (menu, varnames, objects);

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Playback Menu  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::playback_menu (Gtk::Window *toplevel, intf_thread_t *p_intf)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Playback")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  vlc_object_t *p_object;
  std::vector<int> objects;
  std::vector<const char *> varnames;

  Gtk::ImageMenuItem *image_item;
  ADD_IMG_ITEM ("vlc_gototime.png", I_MENU_GOTOTIME, GDK_T, Gdk::CONTROL_MASK);
  //image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::gototime));

  p_object = (vlc_object_t *)vlc_object_find(p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE);
  if (p_object != NULL)
  {
    //ADD_SEPARATOR;

    PUSH_VAR ("bookmark");
    PUSH_VAR ("title");
    PUSH_VAR ("chapter");
    PUSH_VAR ("program");
    PUSH_VAR ("navigation");
    PUSH_VAR ("dvd_menus");

    PUSH_VAR ("prev-title");
    PUSH_VAR ("next-title");
    PUSH_VAR ("prev-chapter");
    PUSH_VAR ("next-chapter");
    vlc_object_release (p_object);
  }
  Populate (menu, varnames, objects);

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Help Menu  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::help_menu (Gtk::Window *toplevel)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Help")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item;

  ADD_IMG_ITEM ("vlc_help.png", "Help...", GDK_F1, Gdk::LOCK_MASK);
  //image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::help));
#ifdef UPDATE_CHECK
  Gtk::MenuItem *s_item = new Gtk::MenuItem (_("Update"), true);
  menu->append (*Gtk::manage (s_item));
#endif
  ADD_SEPARATOR;
  ADD_IMG_ITEM ("vlc_about.png", I_MENU_ABOUT, GDK_U, Gdk::CONTROL_MASK);
  //image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::about));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// FIXME : connect events
// Service Discovery Playlist Submenu - - - - - - - - - - - - - - - - - - - - -
Gtk::MenuItem*
GVLCMenu::playlist_sd_submenu (intf_thread_t *p_intf)
{

  Gtk::MenuItem *item = new Gtk::MenuItem (_(I_PL_SD));
  Gtk::Menu *menu = new Gtk::Menu ();

  char **ppsz_longnames;
  char **ppsz_names = services_discovery_GetServicesNames (p_intf, &ppsz_longnames);
  char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
  
  for (; *ppsz_name; ppsz_name++, ppsz_longname++)
   {
    
    Gtk::CheckMenuItem *check_menu = new Gtk::CheckMenuItem (*ppsz_longname);
    menu->append (*Gtk::manage (check_menu));
    
    if (playlist_IsServicesDiscoveryLoaded (p_intf->p_sys->p_playlist, *ppsz_name))
      check_menu->set_active (true);
      
    if (!strcmp (*ppsz_name, "podcast"))
     {
      Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("Configure podcasts..."));
      menu->append (*Gtk::manage (sub_item));
     }
      
    free (*ppsz_name);
    free (*ppsz_longname);

   }
   
  free (ppsz_names);
  free (ppsz_longnames);
 
  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// Builders for automenus - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
GVLCMenu::Populate(Gtk::Menu *menu,
                         std::vector<const char *> & varnames,
                         std::vector<int> & objects)
{
//  current_group = NULL;
  vlc_object_t *p_object;
  bool b_section_empty = false;
  int i;

#define APPEND_EMPTY {Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("Empty"));\
                      sub_item->set_sensitive (false);\
                      menu->append (*Gtk::manage (sub_item)); }

  for (i = 0; i < ( int )objects.size () ; i++)
  {
    if (!varnames[i] || !*varnames[i])
    {
      if (b_section_empty)
        APPEND_EMPTY;
      ADD_SEPARATOR;
      b_section_empty = true;
      continue;
    }

    if (objects[i] == 0)
    {
      // FIXME ? bug What is this ?
      // Append (menu, varnames[i], NULL);
      b_section_empty = false;
      continue;
    }

    p_object = (vlc_object_t *)vlc_object_get (objects[i]);
    if (p_object == NULL) continue;

    b_section_empty = false;
    // Ugly specific stuff
    if (strstr ( varnames[i], "intf-add"))
      CreateItem (menu, varnames[i], p_object, false);
    else
      CreateItem (menu, varnames[i], p_object, true);
    vlc_object_release (p_object);
  }

  // Special case for empty menus
  if (menu->items ().glist () == NULL || b_section_empty)
    APPEND_EMPTY

}
#undef APPEND_EMPTY

bool
GVLCMenu::IsMenuEmpty (const char *psz_var, vlc_object_t *p_object, bool b_root = true )
{
  vlc_value_t val, val_list;
  int i_type, i_result, i;

  // Check the type of the object variable
  i_type = var_Type (p_object, psz_var);

  // Check if we want to display the variable
  if (!(i_type & VLC_VAR_HASCHOICE)) return false;

  var_Change (p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL);
  if (val.i_int == 0) return true;

  if ((i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE)
  {
    if (val.i_int == 1 && b_root) return true;
    else return false;
  }

  // Check children variables in case of VLC_VAR_VARIABLE
  if (var_Change (p_object, psz_var, VLC_VAR_GETLIST, &val_list, NULL) < 0)
  {
    return true;
  }

  for (i = 0, i_result = true; i < val_list.p_list->i_count; i++)
  {
    if (!IsMenuEmpty (val_list.p_list->p_values[i].psz_string, p_object, false))
    {
      i_result = false;
      break;
    }
  }

  // clean up everything
  var_Change (p_object, psz_var, VLC_VAR_FREELIST, &val_list, NULL);

  return i_result;

}

void
GVLCMenu::CreateItem (Gtk::Menu *menu, const char *psz_var, vlc_object_t *p_object, bool b_submenu)
{
  vlc_value_t val, text;
  int i_type;

  // Check the type of the object variable
  i_type = var_Type (p_object, psz_var);

  switch (i_type & VLC_VAR_TYPE)
  {
    case VLC_VAR_VOID:
    case VLC_VAR_BOOL:
    case VLC_VAR_VARIABLE:
    case VLC_VAR_STRING:
    case VLC_VAR_INTEGER:
    case VLC_VAR_FLOAT:
      break;
    default:
    // Variable doesn't exist or isn't handled
    return;
  }

  if (IsMenuEmpty (psz_var, p_object)) return;

  // Get the descriptive name of the variable
  var_Change (p_object, psz_var, VLC_VAR_GETTEXT, &text, NULL);

  if (i_type & VLC_VAR_HASCHOICE)
  {
    // Append choices menu
    if (b_submenu)
    {
      Gtk::MenuItem *item = new Gtk::MenuItem (Glib::ustring (text.psz_string ? text.psz_string : psz_var));
      Gtk::Menu *submenu = new Gtk::Menu ();
      if (CreateChoicesMenu (submenu, psz_var, p_object, true) == 0)
      {
        item->set_submenu (*Gtk::manage (submenu));
      }
      menu->append (*Gtk::manage (item));
    }
    else
      CreateChoicesMenu (menu, psz_var, p_object, true);
    FREENULL (text.psz_string);
    return;
  }

#define TEXT_OR_VAR Glib::ustring (text.psz_string ? text.psz_string : psz_var)

  switch (i_type & VLC_VAR_TYPE)
  {
    case VLC_VAR_VOID:
      var_Get (p_object, psz_var, &val);
      CreateAndConnect (menu, psz_var, TEXT_OR_VAR, "", ITEM_NORMAL,
                        p_object->i_object_id, val, i_type);
      break;

    case VLC_VAR_BOOL:
      var_Get (p_object, psz_var, &val);
      val.b_bool = !val.b_bool;
      CreateAndConnect (menu, psz_var, TEXT_OR_VAR, "", ITEM_CHECK,
                        p_object->i_object_id, val, i_type, !val.b_bool);
      break;
  }
  FREENULL (text.psz_string);

}

int
GVLCMenu::CreateChoicesMenu (Gtk::Menu *submenu, const char *psz_var, vlc_object_t *p_object, bool b_root)
{
  vlc_value_t val, val_list, text_list;
  int i_type, i;

  // Check the type of the object variable
  i_type = var_Type (p_object, psz_var);

  // Make sure we want to display the variable
  if (IsMenuEmpty (psz_var, p_object, b_root)) return VLC_EGENERIC;

  switch (i_type & VLC_VAR_TYPE)
  {
    case VLC_VAR_VOID:
    case VLC_VAR_BOOL:
    case VLC_VAR_VARIABLE:
    case VLC_VAR_STRING:
    case VLC_VAR_INTEGER:
    case VLC_VAR_FLOAT:
      break;
    default:
      // Variable doesn't exist or isn't handled
      return VLC_EGENERIC;
  }

  if (var_Change (p_object, psz_var, VLC_VAR_GETLIST, &val_list, &text_list) < 0)
  {
    return VLC_EGENERIC;
  }

#define NORMAL_OR_RADIO i_type & VLC_VAR_ISCOMMAND ? ITEM_NORMAL : ITEM_RADIO
#define NOTCOMMAND !(i_type & VLC_VAR_ISCOMMAND)
#define CURVAL val_list.p_list->p_values[i]
#define CURTEXT text_list.p_list->p_values[i].psz_string

  for (i = 0; i < val_list.p_list->i_count; i++)
  {
    vlc_value_t another_val;
    std::stringstream menutext;
    Gtk::Menu *subsubmenu = new Gtk::Menu ();
    Gtk::MenuItem *item = new Gtk::MenuItem (Glib::ustring (CURTEXT ? CURTEXT : CURVAL.psz_string), true);

    switch (i_type & VLC_VAR_TYPE)
    {
      case VLC_VAR_VARIABLE:
        CreateChoicesMenu (subsubmenu, CURVAL.psz_string, p_object, false );
        item->set_submenu (*Gtk::manage (subsubmenu));
        submenu->append (*Gtk::manage (item));
        break;

      case VLC_VAR_STRING:
        var_Get (p_object, psz_var, &val);
        another_val.psz_string = strdup (CURVAL.psz_string);
        menutext << (CURTEXT ? CURTEXT : another_val.psz_string);
        CreateAndConnect (submenu, psz_var, menutext.str ().c_str (), "", NORMAL_OR_RADIO,
                          p_object->i_object_id, another_val, i_type,
                          NOTCOMMAND && val.psz_string && !strcmp (val.psz_string, CURVAL.psz_string));

        free (val.psz_string);
        break;

      case VLC_VAR_INTEGER:
        var_Get (p_object, psz_var, &val);
        if (CURTEXT) menutext << CURTEXT;
        else menutext << CURVAL.i_int;
        CreateAndConnect (submenu, psz_var, menutext.str ().c_str (), "", NORMAL_OR_RADIO,
                          p_object->i_object_id, CURVAL, i_type,
                          NOTCOMMAND && CURVAL.i_int == val.i_int);
        break;

      case VLC_VAR_FLOAT:
        var_Get( p_object, psz_var, &val );
        if (CURTEXT) menutext << CURTEXT;
        else menutext << std::fixed << std::setprecision (2) << CURVAL.f_float;
        CreateAndConnect (submenu, psz_var, menutext.str ().c_str (), "", NORMAL_OR_RADIO,
                          p_object->i_object_id, CURVAL, i_type,
                          NOTCOMMAND && CURVAL.f_float == val.f_float);
        break;

      default:
        break;
    }
  }
//  current_group = NULL;

  // clean up everything
  var_Change (p_object, psz_var, VLC_VAR_FREELIST, &val_list, &text_list);

#undef NORMAL_OR_RADIO
#undef NOTCOMMAND
#undef CURVAL
#undef CURTEXT
  return VLC_SUCCESS;

}

void
GVLCMenu::CreateAndConnect (Gtk::Menu *menu, const char *psz_var, Glib::ustring text, Glib::ustring help,
                            int i_item_type, int i_object_id, vlc_value_t val, int i_val_type, bool checked)
{

//FIXME add help ToolTip

  if (i_item_type == ITEM_CHECK)
  {
    Gtk::CheckMenuItem *item_check = new Gtk::CheckMenuItem (text);
    if (checked) item_check->set_active ();
    menu->append (*Gtk::manage (item_check));
  }
  else if (i_item_type == ITEM_RADIO)
  {
//    if (!current_group) current_group = 0;
    Gtk::RadioMenuItem *item_radio = new Gtk::RadioMenuItem (current_group, text, false);
    if (checked) item_radio->set_active ();
    menu->append (*Gtk::manage (item_radio));
  }
  else
  {
    Gtk::MenuItem *item_normal = new Gtk::MenuItem (text);
    menu->append (*Gtk::manage (item_normal));
  }
//  MenuItemData *itemData = new MenuItemData (i_object_id, i_val_type, val, psz_var);
//  CONNECT( action, triggered(), THEDP->menusMapper, map() );
//  THEDP->menusMapper->setMapping( action, itemData );
}
